package com.ruoyi.business.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.business.*;
import com.ruoyi.business.ao.RefundAO;
import com.ruoyi.business.bo.*;
import com.ruoyi.business.enums.*;
import com.ruoyi.business.mapper.*;
import com.ruoyi.business.vo.RechargeListVO;
import com.ruoyi.common.common.CommonEnum;
import com.ruoyi.common.common.ResultBody;
import com.ruoyi.common.exception.BizException;
import com.ruoyi.common.utils.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


/**
 * @author ：jiangguanjun
 * @description：充值
 * @date ：2020/7/16 21:13
 */
@Slf4j
@Component
public class RechargeService {

    @Autowired
    private RechargeMapper rechargeMapper ;
    @Autowired
    private UserMapper userMapper ;
    @Autowired
    private AccountDetailMapper accountDetailMapper ;

    @Autowired
    private PushMessageService pushMessageService ;

    @Value("${weixin.template.recharge.templateId}")
    private String templateId  ;
    @Value("${weixin.template.recharge.title}")
    private String title  ;

    @Value("${weixin.template.recharge.remark}")
    private String remark  ;
    @Value("${weixinpay.recharge_notify}")
    private String notify  ;

    @Value("${weixinpay.notify_base_url}")
    private String notifyBase  ;
    @Value("${weixinpay.recharge_refund_notify}")
    private String rechargeRefundNotify  ;
    //recharge_refund_notify

    @Autowired
    private PayService payService ;
    @Autowired
    private OrderMapper orderMapper ;

    @Autowired
    private RechargeItemMapper rechargeItemMapper ;

    @Autowired
    private RefundMapper refundMapper ;

    @Transactional
    public ResultBody<PayResultBO> recharge(RechargeBO rechargeBO) {
        RechargeItem rechargeItem = rechargeItemMapper.selectByPrimaryKey(rechargeBO.getRechargeItemId()) ;
        //  插入充值记录
        String orderNo = "recharge"+ IdUtils.getId() ;
        Recharge recharge = new Recharge() ;
        recharge.setMoney(rechargeItem.getMoney());
        recharge.setuId(rechargeBO.getuId());
        recharge.setOrderNo(orderNo);
        if(rechargeItem.getGiveMoney() != null){
            recharge.setGiveMoney(rechargeItem.getGiveMoney());
        }
        int res = rechargeMapper.insertSelective(recharge) ;
        if(res<=0){
            throw new BizException(CommonEnum.RECHARGE_ERROR) ;
        }


        // 插入订单
        Order order = new Order() ;
        order.setMoney(rechargeItem.getMoney());
        order.setuId(rechargeBO.getuId());

        order.setOrderNo(orderNo);
        order.setObjId(recharge.getId());
        order.setOrderType(OrderTypeEnum.RECHARGE.getCode());
        order.settPayTime(new Date());
        log.info("order::::::{}", JSONObject.toJSONString(order));
        res = orderMapper.insertSelective(order) ;
        if(res<0){
            throw new BizException(CommonEnum.RECHARGE_ERROR) ;
        }

        User userDB = userMapper.selectByPrimaryKey(rechargeBO.getuId()) ;

        PayBO payBO = new PayBO() ;
        payBO.setOpenid(userDB.getOpenId());
        payBO.setTotal(rechargeItem.getMoney());
        payBO.setProdName("余额购买");
        String url = notify ;
        log.info("回调地址url:::::{}",url);
        payBO.setNotifyUrl(url);
        payBO.setOutTradeNo(orderNo);
        payBO.setDescription("余额购买");
        PayResultBO payResultBO = payService.pay(payBO) ;
        if(payResultBO == null){
            throw new BizException(CommonEnum.RECHARGE_ERROR) ;
        }

        return ResultBody.success(payResultBO) ;
    }


    public ResultBody listPage(String createStartTime, String createEndTime, Integer uId,String nike) {
        MyPage myPage = PageConfig.getPage() ;
        Page<RechargeListVO> page = new Page<>(myPage.getPageNum(),myPage.getPageSize()) ;


        IPage<RechargeListVO> iPage =  rechargeMapper.selectPageList(page,createStartTime,createEndTime,uId,nike) ;
        return ResultBody.success(iPage) ;
    }

    public List<RechargeListVO> list(String createStartTime, String createEndTime, Integer uId,String nike) {

        List<RechargeListVO>  rechargeListVOs=  rechargeMapper.selectList(createStartTime,createEndTime,uId,nike) ;
        return rechargeListVOs;
    }

    public JSONObject rechargeNotify(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject() ;
        PayNotifyRequest payNotifyRequest = payService.getNotifyData(request) ;
        log.info("充值payNotifyRequest::::::{}",payNotifyRequest);
        if(TradeState.SUCCESS.getCode().equals(payNotifyRequest.getTrade_state())){
            log.info("用户支付成功");
            Recharge recharge = rechargeMapper.selectByOrderNo(payNotifyRequest.getOut_trade_no()) ;
            int giveMoney = recharge.getGiveMoney()==null?0:recharge.getGiveMoney() ;
            User userDB = userMapper.selectByOpenId(payNotifyRequest.getPayer().getOpenid()) ;
            Integer balance = userDB.getBalance()+recharge.getMoney()+giveMoney ;
            userDB.setBalance(balance);
            userDB.setUpdateTime(null);

            int res = userMapper.updateByPrimaryKeySelective(userDB) ;
            if(res<0){
                log.info("更新用户信息失败");
                throw new BizException(CommonEnum.RECHARGE_ERROR) ;
            }
            // 更新账户信息
            AccountDetail accountDetail = new AccountDetail() ;
            accountDetail.setBusiType(AccountBusiTypeEnum.RECHARGE.getCode());
            accountDetail.setBusiId(recharge.getId());
            accountDetail.setMoney(recharge.getMoney()+giveMoney);
            accountDetail.setLastBalance(balance);
            accountDetail.setuId(userDB.getId());
            accountDetailMapper.insertSelective(accountDetail) ;


            recharge.setStatus(1);
            rechargeMapper.updateByPrimaryKeySelective(recharge) ;

            Order order  = new Order() ;
            order.setOrderNo(payNotifyRequest.getOut_trade_no());
            order.setStatus(1);
            res = orderMapper.updateByOrderNo(order) ;
            if(res<0){
                jsonObject.put("code","FAIL") ;
                jsonObject.put("message","订单更新失败") ;
                return jsonObject ;
            }

            // 发送模板消息
            Date d = new Date() ;
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
            String dateStr = format.format(d) ;
            JSONObject keyword1 = new JSONObject() ;
            keyword1.put("value",giveMoney+recharge.getMoney()+"元") ;
            keyword1.put("color","#FF0000") ;
            jsonObject.put("keyword1",keyword1) ;
            JSONObject keyword2 = new JSONObject() ;
            keyword2.put("value",recharge.getMoney()+"元") ;
            jsonObject.put("keyword2",keyword2) ;
            keyword2.put("color","#FF0000") ;
            JSONObject keyword3 = new JSONObject() ;
            keyword3.put("value",dateStr) ;
            jsonObject.put("keyword3",keyword3) ;
            JSONObject keyword4 = new JSONObject() ;
            keyword4.put("value",balance+"元") ;
            jsonObject.put("keyword4",keyword4) ;
            keyword4.put("color","#FF0000") ;
            JSONObject first = new JSONObject() ;
            first.put("value",title) ;
            jsonObject.put("first",title) ;
            JSONObject remarkk = new JSONObject() ;
            remarkk.put("value",remark) ;
            jsonObject.put("remark",remarkk) ;

            pushMessageService.send(jsonObject,templateId,userDB.getOpenId(),"http://www.baidu.com") ;
            return null ;
        }
        if(TradeState.PAYERROR.getCode().equals(payNotifyRequest.getTrade_state())){
            Order order = new Order() ;
            order.setStatus(TradeStatusEnum.PAY_FAIL.getCode());
            order.setOrderNo(payNotifyRequest.getOut_trade_no());
            orderMapper.updateByOrderNo(order) ;
        }
        log.info("支付失败");


        jsonObject.put("code","FAIL") ;
        jsonObject.put("message","支付失败") ;
        return jsonObject ;
    }

    public JSONObject refundNotify(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject() ;
        RefundNotifyRequest refundNotifyRequest = payService.getRefundNotifyData(request) ;
        Refund refund = refundMapper.selectByRefundOutNo(refundNotifyRequest.getOut_refund_no()) ;
        if(refund == null){
            log.warn("未查到退款订单");
            jsonObject.put("code","SUCCESS") ;
            return jsonObject ;
        }
        if(RefundState.SUCCESS.getCode().equals(refund)){
            log.info("状态为成功状态，无需操作");
            jsonObject.put("code","SUCCESS") ;
            return jsonObject ;
        }


        if(RefundState.SUCCESS.getCode().equals(refundNotifyRequest.getRefund_status())){
            log.info("用户退款成功");
            // 获取支付订单
            Order order = orderMapper.selectByPrimaryKey(refund.getOrderId()) ;
            // 获取充值信息 查询充值金额
            Long objId = order.getObjId() ;
            Recharge recharge = rechargeMapper.selectByPrimaryKey(objId) ;

            // 扣减用户余额

            Long uId = recharge.getuId() ;
            User userDB = userMapper.selectByPrimaryKey(uId) ;

            Integer balance = userDB.getBalance()-refundNotifyRequest.getAmount().getRefund()-recharge.getGiveMoney() ;
            userDB.setBalance(balance);
            userDB.setUpdateTime(null);
            int res = userMapper.updateByPrimaryKeySelective(userDB) ;
            if(res<0){
                log.info("更新用户信息失败");
                throw new BizException(CommonEnum.RECHARGE_ERROR) ;
            }
            // 账户明细表中添加退款明细
            AccountDetail accountDetail = new AccountDetail() ;
            accountDetail.setBusiType(AccountBusiTypeEnum.RECHARGE.getCode());
            accountDetail.setBusiId(refund.getId());
            accountDetail.setMoney(refundNotifyRequest.getAmount().getRefund()+recharge.getGiveMoney());
            accountDetail.setLastBalance(balance);
            accountDetail.setuId(userDB.getId());
            accountDetailMapper.insertSelective(accountDetail) ;

            // 更新退款状态
            refund.setStatus(refundNotifyRequest.getRefund_status());
            refund.setUpdateTime(null);
            refund.setUserReceivedAccount(refundNotifyRequest.getUser_received_account());
            refund.setRefundId(refundNotifyRequest.getRefund_id());
            refundMapper.updateByPrimaryKeySelective(refund) ;

            return null ;
        } else {
            refund.setRefundId(refundNotifyRequest.getRefund_id());
            refund.setUserReceivedAccount(refundNotifyRequest.getUser_received_account());
            refund.setStatus(refundNotifyRequest.getRefund_status());
            refund.setUpdateTime(null);
            refundMapper.updateByPrimaryKeySelective(refund) ;
            return null ;
        }

    }

    /*public ResultBody<RefundResult> refund(RefundAO refundAO) {
        Integer id = refundAO.getId() ;
        Recharge recharge = rechargeMapper.selectByPrimaryKey(id) ;
        String orderNo = recharge.getOrderNo() ;
        Order order = orderMapper.selectByOrderNO(orderNo) ;
        RefundBO refundBO = new RefundBO() ;
        refundBO.setOrderId(order.getId());
        String outRefundNo = "rechargeRefund"+IdUtils.getId() ;
        log.info("outRefundNo::::::::::::::{}",outRefundNo);
        refundBO.setOut_refund_no(outRefundNo);
        RefundBO.RefundAmount refundAmount = new RefundBO.RefundAmount() ;
        refundAmount.setRefund(refundAO.getMoney());
        refundBO.setRefundAmount(refundAmount);
        refundBO.setuId(order.getuId());
        refundBO.setReason(refundAO.getReason());
        refundBO.setOut_trade_no(order.getOrderNo());
        refundBO.setNotify_url(notifyBase+rechargeRefundNotify);
        RefundResult refundResult = payService.refundByOut(refundBO) ;
        if(refundResult == null){
            return ResultBody.error("退款失败") ;
        }
        return ResultBody.success(refundResult) ;
    }*/
}
